﻿using Microsoft.Extensions.DependencyInjection;
using PetaPoco;
using PmSoft.Cache.Abstractions;
using PmSoft.Cache.Abstractions.EntityCache;
using PmSoft.Core;
using PmSoft.Core.Domain.Entities;
using PmSoft.Core.Extensions;
using PmSoft.Data.Abstractions;
using System.Diagnostics;

namespace PmSoft.Data.PetaPoco.Repositories;

/// <summary>
/// 带缓存的实体仓储类，继承自 Repository，提供 CRUD 和分页查询的缓存支持
/// </summary>
/// <typeparam name="TDbContext">PetaPoco 数据库上下文类型</typeparam>
/// <typeparam name="TEntity">实体类型，必须实现 IEntity<TKey></typeparam>
/// <typeparam name="TKey">主键类型，不可为空</typeparam>
public class CacheRepository<TDbContext, TEntity, TKey> : Repository<TEntity, TKey>, ICacheRepository<TDbContext, TEntity, TKey>
	where TDbContext : PetaPocoDbContext
	where TEntity : class, IEntity<TKey>, new()
	where TKey : notnull
{
	/// <summary>
	/// 构造函数，初始化仓储和缓存配置
	/// </summary>
	/// <param name="dbContext">数据库上下文</param>
	/// <param name="applicationContext">应用程序上下文</param>
	public CacheRepository(TDbContext dbContext, IApplicationContext applicationContext)
		: base(dbContext, applicationContext)
	{
		CacheablePageCount = 30;        // 默认缓存页数
		PrimaryMaxRecords = 50000;      // 主查询最大记录数
		SecondaryMaxRecords = 5000;     // 次查询最大记录数
	}

	/// <summary>
	/// 缓存服务
	/// </summary>
	protected ICacheService CacheService => ApplicationContext.ServiceProvider.GetRequiredService<ICacheService>();

	/// <summary>
	/// 实体缓存版本服务，根据分布式缓存配置选择对应实现
	/// </summary>
	protected IEntityCacheVersionService<TEntity, TKey> CacheVersionService
	{
		get
		{
			if (CacheService.EnableDistributedCache)
				return ApplicationContext.GetRequiredService<IDistributedEntityCacheVersionService<TEntity, TKey>>();
			return ApplicationContext.GetRequiredService<IEntityCacheVersionService<TEntity, TKey>>();
		}
	}

	/// <summary>
	/// 可缓存的列表页数，默认 30
	/// </summary>
	protected virtual int CacheablePageCount { get; }

	/// <summary>
	/// 主查询最大记录数，默认 50000
	/// </summary>
	protected virtual long PrimaryMaxRecords { get; }

	/// <summary>
	/// 次查询最大记录数，默认 5000
	/// </summary>
	protected virtual int SecondaryMaxRecords { get; }

	#region 同步方法

	/// <summary>
	/// 插入实体到数据库（同步）
	/// </summary>
	/// <param name="entity">要插入的实体</param>
	/// <returns>插入后的主键值</returns>
	public override object Insert(TEntity entity)
	{
		object result = base.Insert(entity);
		OnInserted(entity);
		return result;
	}

	/// <summary>
	/// 插入实体后触发（同步），更新缓存
	/// </summary>
	/// <param name="entity">已插入的实体</param>
	protected virtual void OnInserted(TEntity entity)
	{
		if (CacheVersionService.Metadata.EnableCache)
		{
			CacheVersionService.IncreaseListCacheVersion(entity);
			CacheService.Set(CacheVersionService.GetCacheKeyOfEntity(entity.Id), entity, CacheVersionService.Metadata.CachingExpirationType);
		}
	}

	/// <summary>
	/// 更新数据库中的实体（同步）
	/// </summary>
	/// <param name="entity">要更新的实体</param>
	/// <returns>受影响的行数</returns>
	public override int Update(TEntity entity)
	{
		int result = base.Update(entity);
		if (result > 0) OnUpdated(entity);
		return result;
	}

	/// <summary>
	/// 更新实体后触发（同步），更新缓存
	/// </summary>
	/// <param name="entity">已更新的实体</param>
	protected virtual void OnUpdated(TEntity entity)
	{
		if (CacheVersionService.Metadata.EnableCache)
		{
			CacheVersionService.IncreaseEntityCacheVersion(entity.Id);
			CacheVersionService.IncreaseListCacheVersion(entity);
			CacheService.Set(CacheVersionService.GetCacheKeyOfEntity(entity.Id), entity, CacheVersionService.Metadata.CachingExpirationType);
		}
	}

	/// <summary>
	/// 删除数据库中的实体（同步），支持逻辑删除
	/// </summary>
	/// <param name="entity">要删除的实体</param>
	/// <returns>受影响的行数</returns>
	public override int Delete(TEntity entity)
	{
		if (entity == null) return 0;
		int result = entity is IDelEntity<TKey> delEntity
			? PerformLogicalDelete(delEntity)
			: base.Delete(entity);
		if (result > 0) OnDeleted(entity);
		return result;
	}

	/// <summary>
	/// 执行逻辑删除（同步）
	/// </summary>
	/// <param name="delEntity">支持逻辑删除的实体</param>
	/// <returns>受影响的行数</returns>
	private int PerformLogicalDelete(IDelEntity<TKey> delEntity)
	{
		delEntity.IsDeleted = true;
		delEntity.DeleteToken = delEntity.Id;
		return base.Update((TEntity)delEntity);
	}

	/// <summary>
	/// 删除实体后触发（同步），更新缓存
	/// </summary>
	/// <param name="entity">已删除的实体</param>
	protected virtual void OnDeleted(TEntity entity)
	{
		if (CacheVersionService.Metadata.EnableCache)
		{
			CacheVersionService.IncreaseEntityCacheVersion(entity.Id);
			CacheVersionService.IncreaseListCacheVersion(entity);
			CacheService.Remove(CacheVersionService.GetCacheKeyOfEntity(entity.Id));
		}
	}

	/// <summary>
	/// 根据实体 ID 删除（同步）
	/// </summary>
	/// <param name="entityId">实体 ID</param>
	/// <returns>受影响的行数</returns>
	public override int DeleteByEntityId(TKey entityId)
	{
		TEntity? entity = Get(entityId);
		return entity == null ? 0 : Delete(entity);
	}

	/// <summary>
	/// 获取单个实体（同步），支持缓存
	/// </summary>
	/// <param name="entityId">实体 ID</param>
	/// <returns>实体对象，若不存在或已删除则返回 null</returns>
	public override TEntity? Get(TKey entityId)
	{
		if (entityId == null) throw new ArgumentNullException(nameof(entityId));
		TEntity? entity = CacheVersionService.Metadata.EnableCache
			? CacheService.Get<TEntity>(CacheVersionService.GetCacheKeyOfEntity(entityId))
			: null;

		if (entity == null)
		{
			entity = base.Get(entityId);
			if (entity != null && CacheVersionService.Metadata.EnableCache)
			{
				CacheService.Set(CacheVersionService.GetCacheKeyOfEntity(entity.Id), entity, CacheVersionService.Metadata.CachingExpirationType);
			}
		}

		return FilterDeleted(entity);
	}

	/// <summary>
	/// 过滤已删除的实体
	/// </summary>
	/// <param name="entity">待检查的实体</param>
	/// <returns>未删除的实体或 null</returns>
	private TEntity? FilterDeleted(TEntity? entity)
	{
		if (entity == null) return null;
		return entity is IDelEntity<TKey> delEntity && delEntity.IsDeleted ? null : entity;
	}

	/// <summary>
	/// 获取前 topCount 条实体（同步，带缓存）
	/// </summary>
	/// <param name="topCount">获取的实体数量</param>
	/// <param name="cacheExpiration">缓存过期类型</param>
	/// <param name="generateCacheKey">生成缓存键的函数</param>
	/// <param name="generateSql">生成查询 SQL 的函数</param>
	/// <returns>实体集合</returns>
	public virtual IEnumerable<TEntity> GetTopEntitiesWithCache(int topCount, CachingExpirationType cacheExpiration, Func<string> generateCacheKey, Func<Sql> generateSql)
	{
		string cacheKey = $"AreaCollection:{generateCacheKey()}";
		var cachedEntityIds = CacheService.Get<PagedEntityIdsCollection<TKey>>(cacheKey)
			?? CacheTopEntities(generateSql(), cacheExpiration, cacheKey);
		return GetEntitiesByIds(cachedEntityIds.GetTopIds(topCount));
	}

	/// <summary>
	/// 缓存前 topCount 条实体的 ID
	/// </summary>
	private PagedEntityIdsCollection<TKey> CacheTopEntities(Sql sql, CachingExpirationType cacheExpiration, string cacheKey)
	{
		var topEntityIds = DbContext.FetchTopPrimaryKeys<TEntity, TKey>(SecondaryMaxRecords, sql);
		var cachedEntityIds = new PagedEntityIdsCollection<TKey>(topEntityIds);
		CacheService.Set(cacheKey, cachedEntityIds, cacheExpiration);
		return cachedEntityIds;
	}

	/// <summary>
	/// 根据实体 ID 集合获取实体（同步，自动缓存）
	/// </summary>
	/// <param name="entityIds">实体 ID 集合</param>
	/// <returns>实体集合</returns>
	public virtual IEnumerable<TEntity> GetEntitiesByIds(IEnumerable<TKey> entityIds)
	{
		var entityIdList = ValidateEntityIds(entityIds);
		if (!entityIdList.Any()) return Enumerable.Empty<TEntity>();

		var entities = FetchEntitiesWithCache(entityIdList);
		return FilterValidEntities(entities);
	}

	/// <summary>
	/// 验证实体 ID 集合
	/// </summary>
	private List<TKey> ValidateEntityIds(IEnumerable<TKey> entityIds)
	{
		if (entityIds == null) throw new ArgumentNullException(nameof(entityIds));
		var entityIdList = entityIds.Where(x => x != null).Distinct().ToList();
		if (entityIdList.Count > 2000) throw new ArgumentOutOfRangeException(nameof(entityIds), "实体 ID 集合不能超过 2000");
		return entityIdList;
	}

	/// <summary>
	/// 从缓存或数据库获取实体
	/// </summary>
	private TEntity?[] FetchEntitiesWithCache(List<TKey> entityIdList)
	{
		var entitiesInMemory = new TEntity?[entityIdList.Count];
		var missingEntityIds = new Dictionary<TKey, int>();
		var entityCacheKeys = CacheVersionService.GetCacheKeyOfEntitys(entityIdList);

		for (int i = 0; i < entityIdList.Count; i++)
		{
			TKey entityId = entityIdList[i];
			string cacheKey = entityCacheKeys[entityId.ToString() ?? throw new ArgumentNullException(nameof(entityId))];
			TEntity? cachedEntity = CacheService.Get<TEntity>(cacheKey);
			entitiesInMemory[i] = cachedEntity ?? null;
			if (cachedEntity == null) missingEntityIds[entityId] = i;
		}

		if (missingEntityIds.Any())
		{
			var entitiesFromDb = DbContext.FetchByPrimaryKeys<TEntity, TKey>(missingEntityIds.Keys);
			foreach (var entity in entitiesFromDb)
			{
				int index = missingEntityIds[entity.Id];
				entitiesInMemory[index] = entity;
				if (CacheVersionService.Metadata.EnableCache)
				{
					CacheService.Set(CacheVersionService.GetCacheKeyOfEntity(entity.Id), entity, CacheVersionService.Metadata.CachingExpirationType);
				}
			}
		}

		return entitiesInMemory;
	}

	/// <summary>
	/// 过滤有效实体
	/// </summary>
	private IEnumerable<TEntity> FilterValidEntities(TEntity?[] entities)
	{
		var validEntities = entities
			.Where(e => e != null && (!(e is IDelEntity<TKey> del) || !del.IsDeleted))
			.Cast<TEntity>()
			.ToList();
		return validEntities.Any() ? validEntities : Enumerable.Empty<TEntity>();
	}

	/// <summary>
	/// 获取分页实体（同步，主键不缓存，实体缓存）
	/// </summary>
	/// <param name="sql">查询 SQL</param>
	/// <param name="pageIndex">页码，默认 1</param>
	/// <param name="pageSize">每页大小，默认 20</param>
	/// <returns>分页结果</returns>
	protected virtual IPagedList<TEntity> GetPagedEntities(Sql sql, int pageIndex = 1, int pageSize = 20)
	{
		var stopwatch = Stopwatch.StartNew();
		var pagedEntityIds = DbContext.FetchPagingPrimaryKeys<TEntity, TKey>(PrimaryMaxRecords, pageSize, pageIndex, sql);
		var entities = GetEntitiesByIds(pagedEntityIds.PagedIds);
		stopwatch.Stop();

		return new PagedList<TEntity>(entities)
		{
			Total = pagedEntityIds.TotalRecords,
			PageIndex = pageIndex,
			PageSize = pageSize,
			QueryDuration = stopwatch.ElapsedMilliseconds
		};
	}

	/// <summary>
	/// 获取分页实体（同步，提前缓存多页数据）
	/// </summary>
	/// <param name="pageSize">每页大小</param>
	/// <param name="pageIndex">页码</param>
	/// <param name="cachingExpirationTypes">缓存过期类型</param>
	/// <param name="getCacheKey">生成缓存键的函数</param>
	/// <param name="generateSql">生成查询 SQL 的函数</param>
	/// <returns>分页结果</returns>
	protected virtual IPagedList<TEntity> GetPagingEntities(int pageSize, int pageIndex, CachingExpirationType cachingExpirationTypes, Func<string> getCacheKey, Func<Sql> generateSql)
	{
		var stopwatch = Stopwatch.StartNew();
		var pagedEntityIds = FetchOrCachePagedEntityIds(pageIndex, pageSize, cachingExpirationTypes, getCacheKey, generateSql);
		var entities = GetEntitiesByIds(pagedEntityIds.GetPagedIds(pageSize, pageIndex));
		stopwatch.Stop();

		return new PagedList<TEntity>(entities)
		{
			Total = pagedEntityIds.TotalRecords,
			PageIndex = pageIndex,
			PageSize = pageSize,
			QueryDuration = stopwatch.ElapsedMilliseconds
		};
	}

	/// <summary>
	/// 获取或缓存分页实体 ID
	/// </summary>
	private PagedEntityIdsCollection<TKey> FetchOrCachePagedEntityIds(int pageIndex, int pageSize, CachingExpirationType cachingExpirationTypes, Func<string> getCacheKey, Func<Sql> generateSql)
	{
		if (pageIndex < CacheablePageCount && pageSize <= SecondaryMaxRecords)
		{
			string cacheKey = getCacheKey();
			var cachedIds = CacheService.Get<PagedEntityIdsCollection<TKey>>(cacheKey);
			if (cachedIds != null) return cachedIds;

			var pagedIds = DbContext.FetchPagingPrimaryKeys<TEntity, TKey>(PrimaryMaxRecords, pageSize * CacheablePageCount, 1, generateSql());
			pagedIds.HasMultiplePages = true;
			CacheService.Set(cacheKey, pagedIds, cachingExpirationTypes);
			return pagedIds;
		}
		return DbContext.FetchPagingPrimaryKeys<TEntity, TKey>(PrimaryMaxRecords, pageSize, pageIndex, generateSql());
	}

	#endregion

	#region 异步方法

	/// <summary>
	/// 插入实体到数据库（异步）
	/// </summary>
	/// <param name="entity">要插入的实体</param>
	/// <returns>插入后的主键值</returns>
	public override async Task<object> InsertAsync(TEntity entity)
	{
		object result = await base.InsertAsync(entity);
		await OnInsertedAsync(entity);
		return result;
	}

	/// <summary>
	/// 插入实体后触发（异步），更新缓存
	/// </summary>
	/// <param name="entity">已插入的实体</param>
	protected virtual async Task OnInsertedAsync(TEntity entity)
	{
		if (CacheVersionService.Metadata.EnableCache)
		{
			await CacheVersionService.IncreaseListCacheVersionAsync(entity);
			await CacheService.SetAsync(CacheVersionService.GetCacheKeyOfEntity(entity.Id), entity, CacheVersionService.Metadata.CachingExpirationType);
		}
	}

	/// <summary>
	/// 更新数据库中的实体（异步）
	/// </summary>
	/// <param name="entity">要更新的实体</param>
	/// <returns>受影响的行数</returns>
	public override async Task<int> UpdateAsync(TEntity entity)
	{
		int result = await base.UpdateAsync(entity);
		if (result > 0) await OnUpdatedAsync(entity);
		return result;
	}

	/// <summary>
	/// 更新实体后触发（异步），更新缓存
	/// </summary>
	/// <param name="entity">已更新的实体</param>
	protected virtual async Task OnUpdatedAsync(TEntity entity)
	{
		if (CacheVersionService.Metadata.EnableCache)
		{
			await CacheVersionService.IncreaseEntityCacheVersionAsync(entity.Id);
			await CacheVersionService.IncreaseListCacheVersionAsync(entity);
			await CacheService.SetAsync(CacheVersionService.GetCacheKeyOfEntity(entity.Id), entity, CacheVersionService.Metadata.CachingExpirationType);
		}
	}

	/// <summary>
	/// 删除数据库中的实体（异步），支持逻辑删除
	/// </summary>
	/// <param name="entity">要删除的实体</param>
	/// <returns>受影响的行数</returns>
	public override async Task<int> DeleteAsync(TEntity entity)
	{
		if (entity == null) return 0;
		int result = entity is IDelEntity<TKey> delEntity
			? await PerformLogicalDeleteAsync(delEntity)
			: await base.DeleteAsync(entity);
		if (result > 0) await OnDeletedAsync(entity);
		return result;
	}

	/// <summary>
	/// 执行逻辑删除（异步）
	/// </summary>
	/// <param name="delEntity">支持逻辑删除的实体</param>
	/// <returns>受影响的行数</returns>
	private async Task<int> PerformLogicalDeleteAsync(IDelEntity<TKey> delEntity)
	{
		delEntity.IsDeleted = true;
		delEntity.DeleteToken = delEntity.Id;
		return await base.UpdateAsync((TEntity)delEntity);
	}

	/// <summary>
	/// 删除实体后触发（异步），更新缓存
	/// </summary>
	/// <param name="entity">已删除的实体</param>
	protected virtual async Task OnDeletedAsync(TEntity entity)
	{
		if (CacheVersionService.Metadata.EnableCache)
		{
			await CacheVersionService.IncreaseEntityCacheVersionAsync(entity.Id);
			await CacheVersionService.IncreaseListCacheVersionAsync(entity);
			await CacheService.RemoveAsync(CacheVersionService.GetCacheKeyOfEntity(entity.Id));
		}
	}
 
	/// <summary>
	/// 根据实体 ID 删除（异步）
	/// </summary>
	/// <param name="entityId">实体 ID</param>
	/// <returns>受影响的行数</returns>
	public override async Task<int> DeleteByEntityIdAsync(TKey entityId)
	{
		TEntity? entity = await GetAsync(entityId);
		return entity == null ? 0 : await DeleteAsync(entity);
	}

	/// <summary>
	/// 获取单个实体（异步），支持缓存
	/// </summary>
	/// <param name="entityId">实体 ID</param>
	/// <returns>实体对象，若不存在或已删除则返回 null</returns>
	public override async Task<TEntity?> GetAsync(TKey entityId)
	{
		if (entityId == null) throw new ArgumentNullException(nameof(entityId));
		TEntity? entity = CacheVersionService.Metadata.EnableCache
			? await CacheService.GetAsync<TEntity>(await CacheVersionService.GetCacheKeyOfEntityAsync(entityId))
			: null;

		if (entity == null)
		{
			entity = await base.GetAsync(entityId);
			if (entity != null && CacheVersionService.Metadata.EnableCache)
			{
				string cacheKey = await CacheVersionService.GetCacheKeyOfEntityAsync(entity.Id);
				await CacheService.SetAsync(cacheKey, entity, CacheVersionService.Metadata.CachingExpirationType);
			}
		}

		return FilterDeleted(entity);
	}

	/// <summary>
	/// 获取前 topCount 条实体（异步，带缓存）
	/// </summary>
	/// <param name="topCount">获取的实体数量</param>
	/// <param name="cacheExpiration">缓存过期类型</param>
	/// <param name="generateCacheKey">生成缓存键的函数</param>
	/// <param name="generateSql">生成查询 SQL 的函数</param>
	/// <returns>实体集合</returns>
	public virtual async Task<IEnumerable<TEntity>> GetTopEntitiesWithCacheAsync(int topCount, CachingExpirationType cacheExpiration, Func<string> generateCacheKey, Func<Sql> generateSql)
	{
		string cacheKey = $"AreaCollection:{generateCacheKey()}";
		var cachedEntityIds = await CacheService.GetAsync<PagedEntityIdsCollection<TKey>>(cacheKey)
			?? await CacheTopEntitiesAsync(generateSql(), cacheExpiration, cacheKey);
		return await GetEntitiesByIdsAsync(cachedEntityIds.GetTopIds(topCount));
	}

	/// <summary>
	/// 缓存前 topCount 条实体的 ID（异步）
	/// </summary>
	private async Task<PagedEntityIdsCollection<TKey>> CacheTopEntitiesAsync(Sql sql, CachingExpirationType cacheExpiration, string cacheKey)
	{
		var topEntityIds = await DbContext.FetchTopPrimaryKeysAsync<TEntity, TKey>(SecondaryMaxRecords, sql);
		var cachedEntityIds = new PagedEntityIdsCollection<TKey>(topEntityIds);
		await CacheService.SetAsync(cacheKey, cachedEntityIds, cacheExpiration);
		return cachedEntityIds;
	}

	/// <summary>
	/// 根据实体 ID 集合获取实体（异步，自动缓存）
	/// </summary>
	/// <param name="entityIds">实体 ID 集合</param>
	/// <returns>实体集合</returns>
	public virtual async Task<IEnumerable<TEntity>> GetEntitiesByIdsAsync(IEnumerable<TKey> entityIds)
	{
		var entityIdList = ValidateEntityIds(entityIds);
		if (!entityIdList.Any()) return Enumerable.Empty<TEntity>();

		var entities = await FetchEntitiesWithCacheAsync(entityIdList);
		return FilterValidEntities(entities);
	}

	/// <summary>
	/// 从缓存或数据库获取实体（异步）
	/// </summary>
	private async Task<TEntity?[]> FetchEntitiesWithCacheAsync(List<TKey> entityIdList)
	{
		if (entityIdList.Count == 0)
			return Enumerable.Empty<TEntity>().ToArray();
		var entitiesInMemory = new TEntity?[entityIdList.Count];
		var missingEntityIds = new Dictionary<TKey, int>();
		var entityCacheKeys = await CacheVersionService.GetCacheKeyOfEntitysAsync(entityIdList);

		for (int i = 0; i < entityIdList.Count; i++)
		{
			TKey entityId = entityIdList[i];
			string cacheKey = entityCacheKeys[entityId.ToString() ?? throw new ArgumentNullException(nameof(entityId))];
			TEntity? cachedEntity = await CacheService.GetAsync<TEntity>(cacheKey);
			entitiesInMemory[i] = cachedEntity ?? null;
			if (cachedEntity == null) missingEntityIds[entityId] = i;
		}

		if (missingEntityIds.Any())
		{
			var entitiesFromDb = await DbContext.FetchByPrimaryKeysAsync<TEntity, TKey>(missingEntityIds.Keys);
			foreach (var entity in entitiesFromDb)
			{
				int index = missingEntityIds[entity.Id];
				entitiesInMemory[index] = entity;
				if (CacheVersionService.Metadata.EnableCache)
				{
					string cacheKey = await CacheVersionService.GetCacheKeyOfEntityAsync(entity.Id);
					await CacheService.SetAsync(cacheKey, entity, CacheVersionService.Metadata.CachingExpirationType);
				}
			}
		}

		return entitiesInMemory;
	}

	/// <summary>
	/// 获取分页实体（异步，主键不缓存，实体缓存）
	/// </summary>
	/// <param name="sql">查询 SQL</param>
	/// <param name="pageIndex">页码，默认 1</param>
	/// <param name="pageSize">每页大小，默认 20</param>
	/// <returns>分页结果</returns>
	protected virtual async Task<IPagedList<TEntity>> GetPagedEntitiesAsync(Sql sql, int pageIndex = 1, int pageSize = 20)
	{
		var stopwatch = Stopwatch.StartNew();
		var pagedEntityIds = await DbContext.FetchPagingPrimaryKeysAsync<TEntity, TKey>(PrimaryMaxRecords, pageSize, pageIndex, sql);
		var entities = await GetEntitiesByIdsAsync(pagedEntityIds.PagedIds);
		stopwatch.Stop();

		return new PagedList<TEntity>(entities)
		{
			Total = pagedEntityIds.TotalRecords,
			PageIndex = pageIndex,
			PageSize = pageSize,
			QueryDuration = stopwatch.ElapsedMilliseconds
		};
	}

	/// <summary>
	/// 获取分页实体（异步，提前缓存多页数据）
	/// </summary>
	/// <param name="pageSize">每页大小</param>
	/// <param name="pageIndex">页码</param>
	/// <param name="cachingExpirationTypes">缓存过期类型</param>
	/// <param name="getCacheKey">生成缓存键的函数</param>
	/// <param name="generateSql">生成查询 SQL 的函数</param>
	/// <returns>分页结果</returns>
	protected virtual async Task<IPagedList<TEntity>> GetPagingEntitiesAsync(int pageSize, int pageIndex, CachingExpirationType cachingExpirationTypes, Func<string> getCacheKey, Func<Sql> generateSql)
	{
		var stopwatch = Stopwatch.StartNew();
		var pagedEntityIds = await FetchOrCachePagedEntityIdsAsync(pageIndex, pageSize, cachingExpirationTypes, getCacheKey, generateSql);
		var entities = await GetEntitiesByIdsAsync(pagedEntityIds.GetPagedIds(pageSize, pageIndex));
		stopwatch.Stop();

		return new PagedList<TEntity>(entities)
		{
			Total = pagedEntityIds.TotalRecords,
			PageIndex = pageIndex,
			PageSize = pageSize,
			QueryDuration = stopwatch.ElapsedMilliseconds
		};
	}

	/// <summary>
	/// 获取或缓存分页实体 ID（异步）
	/// </summary>
	private async Task<PagedEntityIdsCollection<TKey>> FetchOrCachePagedEntityIdsAsync(int pageIndex, int pageSize, CachingExpirationType cachingExpirationTypes, Func<string> getCacheKey, Func<Sql> generateSql)
	{
		if (pageIndex < CacheablePageCount && pageSize <= SecondaryMaxRecords)
		{
			string cacheKey = getCacheKey();
			var cachedIds = await CacheService.GetAsync<PagedEntityIdsCollection<TKey>>(cacheKey);
			if (cachedIds != null) return cachedIds;

			var pagedIds = await DbContext.FetchPagingPrimaryKeysAsync<TEntity, TKey>(PrimaryMaxRecords, pageSize * CacheablePageCount, 1, generateSql());
			pagedIds.HasMultiplePages = true;
			await CacheService.SetAsync(cacheKey, pagedIds, cachingExpirationTypes);
			return pagedIds;
		}
		return await DbContext.FetchPagingPrimaryKeysAsync<TEntity, TKey>(PrimaryMaxRecords, pageSize, pageIndex, generateSql());
	}

	#endregion
}